﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DtuService;
using System.Threading.Tasks;
using SuperSocket.SocketBase;
using Busness;
using NetCommand;

namespace DtuService
{
    public struct DeviceInfo
    {
        public UInt16   DeviceAreaID;   // 区域ID
        public byte     DeviceID;       // 设备ID
        public UInt16[]   MotherboardID;  // 主板ID
        public Int16    RunTime;        // 运行时间
        public byte     UserLevel;      // 用户等级
        public byte     SiteID;         // 归属站点ID
        public byte[]   CPU_ID;  //CPU ID
    }

    public delegate void DeviceDataResponse(NetCommand.NetCommand cmd);
    public struct AsyncDeviceDataRsponse
    {
        public float waitTimeInSec;
        public DeviceDataResponse deviceDataResponseDelegate;
    }

    public class Device : Client
    {
        private Dictionary<ushort, AsyncDeviceDataRsponse> deviceDataResponseList = new Dictionary<ushort, AsyncDeviceDataRsponse>();

        public DeviceDataResponse DeviceDataUpdate;
        private bool isRegist = false;
        public Device(ByteSession tcp)
            : base(tcp)
        { 
        }
        public DeviceInfo Device_Info;

        protected void registDevice(NetCommand.NetCommand cmd)
        {
            Device_Info.DeviceAreaID = cmd.Header.CMD_AREA_ID;
            Device_Info.DeviceID = cmd.Header.CMD_DEVICE_ID;
            Device_Info.MotherboardID = new ushort[4] { 0, 0, 0, 0 };
            byte siteId = NetCommand.EncodingTools.intToByte(Busness.Business.getInstance().selectSiteId(Device_Info.DeviceID, Device_Info.DeviceAreaID));
            Device_Info.SiteID = siteId;
            isRegist = true;

            string key = Device_Info.DeviceAreaID.ToString() + "_" + Device_Info.DeviceID;
            ServerMain.GetService<DeviceService>().InsertDevice(key, this);
            // 注册到用户
            int userId = Busness.Business.getInstance().getUserId(Device_Info.DeviceAreaID, Device_Info.DeviceID);
            ID = userId;
            User user = ServerMain.GetService<UserService>().GetUser(userId);
            if (user != null)
            {
                //user.AddDevice(this);
            }
        }

        public void ProcessUserCommand(NetCommand.CMD_ID_DEFINE DEV_CMD_ID, DeviceDataResponse responseEvent)
        {
            NetCommand.NetCommand cmd = (NetCommand.NetCommand)NetCommand.NetCommandFactory.GetCommand((ushort)DEV_CMD_ID);
            if (cmd == null)
            {
                return;
            }
            cmd.Header.CMD_AREA_ID = Device_Info.DeviceAreaID;
            cmd.Header.CMD_DEVICE_ID = Device_Info.DeviceID;
            cmd.Header.CMD_FRONT_ID = NetCommand.NetCommon.S2C_HEADER_CODE;
            cmd.Header.CMD_R_W = NetCommand.NetCommon.S2D_READ;
            AsyncDeviceDataRsponse asyncResponse = default(AsyncDeviceDataRsponse);
            asyncResponse.deviceDataResponseDelegate = responseEvent;
            ushort id = (ushort)((ushort)DEV_CMD_ID + NetCommand.NetCommon.S2D_READ * 1000);
            if (deviceDataResponseList.ContainsKey(id))
            {
                deviceDataResponseList[id] = asyncResponse;
            }
            else
            {
                deviceDataResponseList.Add(id, asyncResponse);
            }
            SendMessage(cmd);
        }

        protected override void receiveDeviceMessage(NetCommand.NetCommand cmd)
        {
            NetCommand.CMD_ID_DEFINE CMD_ID = (NetCommand.CMD_ID_DEFINE)cmd.Header.CMD_ID;
            ushort id = 0;
            if (cmd.R_W == NetCommand.NetCommon.S2D_WRITE)
            {
                id = (ushort)(cmd.Header.CMD_ID + (ushort)NetCommand.NetCommon.S2D_WRITE * 1000);
                if (deviceDataResponseList.ContainsKey(id))
                {
                    deviceDataResponseList[id].deviceDataResponseDelegate(cmd);
                    deviceDataResponseList.Remove(id);
                }
                return;
            }
            if (isRegist == false)
            {
                registDevice(cmd);
            }
            switchCmd(cmd, CMD_ID);

            id = (ushort)(cmd.Header.CMD_ID + (ushort)NetCommand.NetCommon.S2D_READ * 1000);
            if (deviceDataResponseList.ContainsKey(id))
            {
                deviceDataResponseList[id].deviceDataResponseDelegate(cmd);
                deviceDataResponseList.Remove(id);
            }
        }

        public void ClearDeviceDataResponse()
        {
            deviceDataResponseList.Clear();
        }

        // TODO
        private void switchCmd(NetCommand.NetCommand cmd, NetCommand.CMD_ID_DEFINE CMD_ID)
        {
            switch (CMD_ID)
            {
                default:
                    break;
            }
        }
        
        public override void Update(float deltaTime)
        {
            Dictionary<ushort, AsyncDeviceDataRsponse> temp = new Dictionary<ushort, AsyncDeviceDataRsponse>(deviceDataResponseList);
            foreach (KeyValuePair<ushort, AsyncDeviceDataRsponse> response in temp)
            {
                AsyncDeviceDataRsponse respValue = response.Value;
                respValue.waitTimeInSec += deltaTime;
                if (respValue.waitTimeInSec >= NetCommand.NetCommon.OUT_TIME_IN_SEC)
                {
                    // 等待超时
                    NetCommand.NetCommand cmd = new NetCommand.NetCommand();
                    cmd.ErrorCode = NetCommand.NetCode.CMD_ERR_TIME_OUT;
                    respValue.deviceDataResponseDelegate(cmd);
                    deviceDataResponseList.Remove(response.Key);
                }
            }
        }
        
        public void SendWriteMessage(NetCommand.NetCommand cmd, DeviceDataResponse complete)
        {
            cmd.Header.CMD_R_W = NetCommand.NetCommon.S2D_WRITE;
            AsyncDeviceDataRsponse respons = default(AsyncDeviceDataRsponse);
            respons.deviceDataResponseDelegate = complete;
            ushort id = (ushort)(cmd.Header.CMD_ID + NetCommand.NetCommon.S2D_WRITE * 1000);
            if (deviceDataResponseList.ContainsKey(id))
            {
                deviceDataResponseList[id] = respons;
            }
            else
            {
                deviceDataResponseList.Add(id, respons);
            }
            SendMessage(cmd);
        }

        public override void OnShutdown()
        {
            User user = ServerMain.GetService<UserService>().GetUser(ID);
            if (user != null)
            {
                //user.DeviceShutdown(this);
            }
            Debug.LogDebug("设备下线 AreaNo = " + Device_Info.DeviceAreaID + "DrvNo = " + Device_Info.DeviceID);
        }

        public override void SendMessage(NetCommand.NetCommand msg)
        {
            if (bSession == null)
            {
                Debug.Log("网络连接不存在");
                return;
            }
            if (bSession.SocketSession == null)
            {
                Debug.Log("网络连接套接字不存在");
                return;
            }
            msg.Header.CMD_FRONT_ID = NetCommon.S2C_HEADER_CODE;
           
            byte[] msgBuffer = NetCommand.CommandTranslator.Instance.EncodeMessage(msg);
            bSession.SendMessage(msgBuffer);
            Debug.Log(EncodingTools.outPut16Number(msgBuffer, msgBuffer[NetCommon.Index_DATA_LEN]));
            Debug.Log("发消息到 : " + this.GetType().FullName + " IP : " + bSession.IPAddress + "\r\n" + msg.ToString());
            
        }

    }
}
